/*
     RoadRunner - an automatic wrapper generation system for Web data sources
     Copyright (C) 2003  Valter Crescenzi - crescenz@dia.uniroma3.it

     This program is  free software;  you can  redistribute it and/or
     modify it  under the terms  of the GNU General Public License as
     published by  the Free Software Foundation;  either version 2 of
     the License, or (at your option) any later version.

     This program is distributed in the hope that it  will be useful,
     but  WITHOUT ANY WARRANTY;  without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
     General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the:

     Free Software Foundation, Inc.,
     59 Temple Place, Suite 330,
     Boston, MA 02111-1307 USA

     ----

     RoadRunner - un sistema per la generazione automatica di wrapper su sorgenti Web
     Copyright (C) 2003  Valter Crescenzi - crescenz@dia.uniroma3.it

     Questo  programma software libero;  lecito redistribuirlo  o
     modificarlo secondo i termini della Licenza Pubblica Generica GNU
     come � pubblicata dalla Free Software Foundation; o la versione 2
     della licenza o (a propria scelta) una versione successiva.

     Questo programma   distribuito nella speranza che sia  utile, ma
     SENZA  ALCUNA GARANZIA;  senza neppure la  garanzia implicita  di
     NEGOZIABILIT�  o di  APPLICABILIT� PER  UN PARTICOLARE  SCOPO. Si
     veda la Licenza Pubblica Generica GNU per avere maggiori dettagli.

     Questo  programma deve  essere  distribuito assieme  ad una copia
     della Licenza Pubblica Generica GNU; in caso contrario, se ne pu
     ottenere  una scrivendo  alla:

     Free  Software Foundation, Inc.,
     59 Temple Place, Suite 330,
     Boston, MA 02111-1307 USA

*/
/*
 * ExpressionIterator.java
 *
 * Created on 27 marzo 2003, 18.04
 */

package com.wolf_datamining.autoextracting.roadrunner.engine;

/**
 *
 * @author  Valter Crescenzi
 */

import java.util.NoSuchElementException;

import com.wolf_datamining.autoextracting.roadrunner.ast.Expression;

public abstract class ExpressionIterator {
    
    private static int counter = 0;
    
    // Si potrebbe passare ad una interfaccia + due implementazioni di supporto:
    // quella attuale pi� SingletonExpressionIterator che servirebbe
    // per il dummy state iniziale di SearchSpace e per gli addHook.
    // No: troppo articolato per usarlo dentro il dummy state e benefici trascurabili.
    // Pattern Iterator + Template Method
    
    private Expression nextResult; // cache of next result
    
    protected int id;
    
    protected ExpressionIterator() {
        this.nextResult = null;
        this.id = counter++;
    }
    
    public int getId() {
        return this.id;
    }
    
    /* This method has to compute next result if exists, null otherwise */
    abstract protected Expression computeNext();
    
    public boolean hasNext() {
        if (this.nextResult!=null) return true; //check if already computed
        this.nextResult = computeNext();
        return (this.nextResult!=null);
    }
    
    public Expression next() {
        if (this.hasNext()) {
            Expression result = this.nextResult;
            this.nextResult = null;
            return result;
        }
        throw new NoSuchElementException(this+" has already expired!");
    }
    
    protected static ExpressionIterator iteratorOverSingleExp(final Expression single) {
        // create a dummy ExpressionIterator for initial expression
        return new ExpressionIterator() {
            private boolean expired = false;
            protected Expression computeNext() {
                if (this.expired) return null;
                this.expired = true; // just one result;
                return single;
            }
        };
    }
    
    protected static ExpressionIterator expiredIterator() {
        return new ExpressionIterator() {
            protected Expression computeNext() {
                return null;
            }
        };
    }
}
